// Learn with Examples, 2020, MIT license
#include <systemc> // include the systemC header file
#include "st1.hh"
#include "st3.hh"
using namespace sc_core; // use namespace


struct FTL_TB : sc_module { // define a systemC module
    tlm_utils::simple_initiator_socket<FTL_TB> tb_isocket;
    SC_CTOR(FTL_TB) {// constructor function, to be explained later
        SC_THREAD(ftl_tb); // register a member function to the kernel
    }
    void ftl_tb(void) ;
};

void FTL_TB::ftl_tb(void) {
        tlm::tlm_generic_payload* trans = new tlm::tlm_generic_payload;
        l2pnode l2ppair;
        std::cout << "ftl test bench init" << std::endl;
        srand(time(NULL));
        for(int i=0;i<16385;i++){
            wait(5, SC_MS);
            // std::cout << "hello" << std::endl;
            l2ppair.lca = rand()%10000;
            l2ppair.pca = rand()%10000;
            trans->set_command( tlm::TLM_WRITE_COMMAND); 
            trans->set_address( 0x11 ); //date read in sbp
            trans->set_data_ptr( reinterpret_cast<unsigned char*>(&l2ppair));
            trans->set_data_length( 8 );
            trans->set_streaming_width( 8 ); // = data_length to indicate no streaming
            trans->set_byte_enable_ptr( 0 ); // 0 indicates unused
            trans->set_dmi_allowed( false ); // Mandatory initial value
            trans->set_response_status( tlm::TLM_INCOMPLETE_RESPONSE ); // Mandatory
            tb_isocket->b_transport( *trans, zerodelay );  // Blocking transport call

        }
    }

int sc_main(int, char*[]) { // entry point
//   hello1(); // approach #1: manually invoke a normal function
    FTL_TB tb("ftl_tb");
    ST1 st1("st1"); // approach #2, instantiate a systemC module
    ST3 st3("st3");
    tb.tb_isocket.bind(st1.st1_tsocket);
    st1.st12st3_isocket.bind(st3.st12st3_tsocket);
    sc_start(); // let systemC simulation kernel to invoke helloworld.hello2();
    return 0;
}